var sampleTags = ["apple", "raspberry", "blackberry", "pine", "pear", "currant", "pineapple", "mango", "cherry"];

var curSuggestions = new Array();

var array = null;
var running = false;

function go(suggestions) {
    array = suggestions;
    if (!running) {
        running = true;
        var result;
        while (array != null) {
            a = array;
            array = null;
            result = mergeSuggestions(a);
        }
        curSuggestions = updateSuggestions(result)
        running = false;
    }
}

function mergeSuggestions(newSuggs) {
    var newSuggestions = new Array();
    var idx = 0, i;

    // removal of duplicated elements
    for (i = 0; i < newSuggs.length; i++) {
        if (newSuggs[i].findIn(newSuggestions) == null) {
            newSuggestions[idx++] = newSuggs[i];
        }
    }

    // merging incoming suggestions with current ones
    var mergedSuggestions = new Array();
    idx = 0;
    var sugg;
    for (i = 0; i < newSuggestions.length; i++) {
        var curSugg = newSuggestions[i].findIn(curSuggestions);
        if (curSugg == null || curSugg.removed) {
            sugg = new Suggestion(newSuggestions[i].tag, null, i);
            mergedSuggestions[idx++] = sugg;
        } else {
            sugg = new Suggestion(curSugg.tag, curSugg.curPos, i);
            mergedSuggestions[idx++] = sugg;
        }
    }

    for (i = 0; i < curSuggestions.length; i++) {
        if (curSuggestions[i].removed) continue;
        var newSugg = curSuggestions[i].findIn(newSuggestions);
        if (newSugg == null) {
            sugg = new Suggestion(curSuggestions[i].tag, curSuggestions[i].curPos, null);
            mergedSuggestions[idx++] = sugg;
        }
    }

    return mergedSuggestions;
}


function updateSuggestions(curSuggestions) {

    var i, sugg;
    for (i = 0; i < curSuggestions.length; i++) {
        sugg = curSuggestions[i];
        if (sugg.newPos != null) {
            if (sugg.curPos == null) {
                addNewSprite(sugg);
            } else {
                moveInToList(sugg);
            }
        } else {
            break;
        }
    }

    var dropBound = i;

    for (; i < curSuggestions.length; i++) {
        sugg = curSuggestions[i];
        moveOutFromList(sugg);
    }

    return curSuggestions;
}

function Suggestion(tag, curPos, newPos) {
    this.tag = tag;
    this.curPos = curPos;
    this.newPos = newPos;
    this.removed = false;

    this.findIn = function(suggestions) {
        for (var i = 0; i < suggestions.length; i++) {
            if (suggestions[i].tag == this.tag && !suggestions[i].removed)
                return suggestions[i];
        }

        return null;
    };

    this.toString = function() {
        return "Suggestion(tag=" + this.tag + ", curPos=" + this.curPos + ", newPos=" + this.newPos + ", removed=" + this.removed + ");"
    }
}


function printSuggestions(suggestions) {
    for (var i = 0; i < suggestions.length; i++) {
        putLine(suggestions[i].toString());
    }
}

function sugTest() {
    var suggs = new Array();

    for (var i = 0; i < 5; i++) {
        suggs[i] = new Suggestion(sampleTags[Math.round(Math.random() * sampleTags.length) % sampleTags.length], null, i);
    }

    go(suggs);

}

function addNewSprite(sugg) {
    var panel = document.getElementById("spritePanel");

    if (document.getElementById("sprite-" + sugg.tag) == null) {
        var sprite = document.createElement("div");
        sprite.setAttribute("id", "sprite-" + sugg.tag);
        sprite.setAttribute("class", "sprite");
        sprite.setAttribute("style", "-webkit-transform: translate3d(500px, 400px, 50px) rotateY(80deg) ; -webkit-transition: -webkit-transform 500ms ease-in-out; -webkit-transform-style: preserve-3d;");
        sprite.appendChild(document.createTextNode(sugg.tag));
        panel.appendChild(sprite);
        setTimeout(function() {
            moveInToList(sugg);
        }, 100);
    }

}

function moveInToList(sugg) {
    if (sugg.newPos != null) {
        var sprite = document.getElementById("sprite-" + sugg.tag);
        if (sprite != null) {
            sprite.addEventListener("webkitTransitionEnd", function() {
                sugg.curPos = sugg.newPos;
            }, false);

            sprite.style.webkitTransition = "-webkit-transform 500ms ease-in-out";
            sprite.style.webkitTransform = "rotateY(0) translate3d(300px, " + (sugg.newPos * 50) + "px, -50px)";
        }
    }
}

function dropSprite(sprite) {
    var panel = document.getElementById("spritePanel");
    try {
        panel.removeChild(sprite);
    } catch (e) {

    }
}

function moveOutFromList(sugg) {
    if (sugg.newPos == null) {
        var sprite = document.getElementById("sprite-" + sugg.tag);
        if (sprite != null) {
            sprite.addEventListener("webkitTransitionEnd", function() {
                sugg.removed = true;
                dropSprite(sprite);
            }, false);

            sprite.style.webkitTransform = "translate3d(100px, 400px, 50px) rotateY(-60deg)";
            sprite.style.webkitTransition = "-webkit-transform 500ms ease-in-out"
        }
    }
}
